#include <gtest/gtest.h>
#include "../utils/test_utils.h"

using namespace TestUtils;

class BasicBuildTest : public ::testing::Test {
protected:
    void SetUp() override {
        cleanupBuildOutputs();
    }
    
    void TearDown() override {
        cleanupBuildOutputs();
    }
};

TEST_F(BasicBuildTest, BasicBuildSuccess) {
    TestScope scope("BasicBuildSuccess");
    
    // 执行基本构建
    auto result = executeBuildCommand(Commands::BUILD_ALL);
    
    // 验证构建成功
    EXPECT_EQ(result.exitCode, 0) << "Build failed with output: " << result.output;
    EXPECT_TRUE(result.containsOutput("Build completed successfully")) 
        << "Success message not found in output: " << result.output;
    
    // 验证构建时间合理
    EXPECT_LT(result.duration, 30000) << "Build took too long: " << result.duration << "ms";
}

TEST_F(BasicBuildTest, CleanFunctionality) {
    TestScope scope("CleanFunctionality");
    
    // 先执行一次构建
    auto buildResult = executeBuildCommand(Commands::BUILD_ALL);
    ASSERT_EQ(buildResult.exitCode, 0) << "Initial build failed";
    
    // 验证构建产物存在
    EXPECT_TRUE(directoryExists(Paths::OUT_RELEASE)) << "Release directory not created";
    EXPECT_TRUE(directoryExists(Paths::OUT_INTERMEDIATE)) << "Intermediate directory not created";
    
    // 执行清理
    auto cleanResult = executeBuildCommand(Commands::BUILD_CLEAN);
    
    // 验证清理成功
    EXPECT_EQ(cleanResult.exitCode, 0) << "Clean failed with output: " << cleanResult.output;
    EXPECT_TRUE(cleanResult.containsOutput("Build completed successfully")) 
        << "Clean success message not found: " << cleanResult.output;
}

TEST_F(BasicBuildTest, BuildSystemInformation) {
    TestScope scope("BuildSystemInformation");
    
    auto result = executeBuildCommand(Commands::BUILD_ALL);
    
    ASSERT_EQ(result.exitCode, 0) << "Build failed";
    
    // 验证构建系统信息输出
    EXPECT_TRUE(result.containsOutput("Phase1 -- Build system information")) 
        << "Build system information phase not found";
    EXPECT_TRUE(result.containsOutput("Build mode:")) 
        << "Build mode information not found";
    EXPECT_TRUE(result.containsOutput("Target platform:")) 
        << "Target platform information not found";
}

TEST_F(BasicBuildTest, ModuleFileLoading) {
    TestScope scope("ModuleFileLoading");
    
    auto result = executeBuildCommand(Commands::BUILD_ALL);
    
    ASSERT_EQ(result.exitCode, 0) << "Build failed";
    
    // 验证模块文件加载
    EXPECT_TRUE(result.containsOutput("Phase2 -- Load module files")) 
        << "Module loading phase not found";
    EXPECT_TRUE(result.containsOutput("Found")) 
        << "Module count information not found";
    EXPECT_TRUE(result.containsOutput("module files:")) 
        << "Module files list not found";
}

TEST_F(BasicBuildTest, DependencyAnalysis) {
    TestScope scope("DependencyAnalysis");
    
    auto result = executeBuildCommand(Commands::BUILD_ALL);
    
    ASSERT_EQ(result.exitCode, 0) << "Build failed";
    
    // 验证依赖分析
    EXPECT_TRUE(result.containsOutput("Phase3 -- Dependency analysis")) 
        << "Dependency analysis phase not found";
    EXPECT_TRUE(result.containsOutput("Auto-resolved dependencies:")) 
        << "Dependency resolution information not found";
}

TEST_F(BasicBuildTest, BuildExecution) {
    TestScope scope("BuildExecution");
    
    auto result = executeBuildCommand(Commands::BUILD_ALL);
    
    ASSERT_EQ(result.exitCode, 0) << "Build failed";
    
    // 验证构建执行阶段
    EXPECT_TRUE(result.containsOutput("Phase4 -- Build execution")) 
        << "Build execution phase not found";
}

TEST_F(BasicBuildTest, BuildPerformance) {
    TestScope scope("BuildPerformance");
    
    // 测试增量构建性能
    auto firstBuild = executeBuildCommand(Commands::BUILD_ALL);
    ASSERT_EQ(firstBuild.exitCode, 0) << "First build failed";
    
    auto secondBuild = executeBuildCommand(Commands::BUILD_ALL);
    ASSERT_EQ(secondBuild.exitCode, 0) << "Second build failed";
    
    // 增量构建应该更快
    EXPECT_LT(secondBuild.duration, firstBuild.duration + 1000) 
        << "Incremental build not optimized. First: " << firstBuild.duration 
        << "ms, Second: " << secondBuild.duration << "ms";
}